package me.yangbajing.helper

import java.sql.{DriverManager, Connection}

import org.squeryl.{Session, SessionFactory}
import org.squeryl.adapters._
import org.squeryl.internals.DatabaseAdapter
import scala.Some
import me.yangbajing.common.MeAdapter
import org.squeryl.logging.{StatementInvocationEvent, StatisticsListener}
import net.liftweb.common.Loggable
import net.liftweb.util.Props

object RdbHelpers {
  def registerSquerylSession() {
    SessionFactory.concreteFactory = Some(() => defaultSession)
  }

  def defaultSession: Session = {
    val db = MeHelpers.config.dbs.head
    session(db.url, db.username, db.password, _adapter(db.adapter))
  }

  def session(url: String, username: String, password: String, adapter: DatabaseAdapter): Session =
    new Session(getConnection(url, username, password), adapter, _myStatisticsListener)

  private def _myStatisticsListener: Option[StatisticsListener] =
    Props.mode match {
      case Props.RunModes.Development => Some(new MyStatisticsListener)
      case _ => None
    }

  def getConnection(url: String, username: String, password: String): Connection =
    DriverManager.getConnection(url, username, password)

  def shutdown() {}


  private def _adapter(v: MeAdapter.Value): DatabaseAdapter =
    v match {
      case MeAdapter.Postgres =>
        _postgresDriver
        new PostgreSqlAdapter

      case MeAdapter.Mysql =>
        _mysqlDriver
        new MySQLInnoDBAdapter

      case MeAdapter.DB2 => new DB2Adapter
      case MeAdapter.Oracle => new OracleAdapter
      case MeAdapter.MSSQL => new MSSQLServer
      case MeAdapter.Derby => new DerbyAdapter
      case MeAdapter.H2 => new H2Adapter
    }

  private lazy val _mysqlDriver = Class.forName("com.mysql.jdbc.Driver")

  private lazy val _postgresDriver = Class.forName("org.postgresql.Driver")
}

class MyStatisticsListener() extends StatisticsListener with Loggable {
  def queryExecuted(se: StatementInvocationEvent) {
    logger.debug("queryExecuted:\n" + se.jdbcStatement)
  }

  def resultSetIterationEnded(statementInvocationId: String, iterationEndTime: Long, rowCount: Int, iterationCompleted: Boolean) {
    logger.debug("resultSetIterationEnded:\n" + s"$statementInvocationId endTime: $iterationEndTime rowCount: $rowCount completed: $iterationCompleted")
  }

  def updateExecuted(se: StatementInvocationEvent) {
    logger.debug("updateExecuted:\n" + se.jdbcStatement)
  }

  def insertExecuted(se: StatementInvocationEvent) {
    logger.debug("insertExecuted:\n" + se.jdbcStatement)
  }

  def deleteExecuted(se: StatementInvocationEvent) {
    logger.debug("deleteExecuted\n" + se.jdbcStatement)
  }

}